package com.tjtt.common.utils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

/**
 * 反射工具类
 * 
 */
public class ReflectUtil {

	/**
	 * 
	 * 取出传入Object对象中的属性值 该方法只适合公共成员变量，对于受保护的变量会抛出异常
	 * 
	 * @param obj: 对象
	 * @param methodName: 属性名
	 * @return Object: 属性值
	 * @throws NoSuchFieldException
	 * @throws SecurityException
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @author wml
	 */
	public static Object getFieldValue(Object obj, String fieldName) throws SecurityException, NoSuchFieldException,
			IllegalArgumentException, IllegalAccessException {
		Class<?> objClass = obj.getClass();
		Field field = objClass.getField(fieldName);
		return field.get(obj);
	}

	/**
	 * 取出传入Object对象的属性值，通过get方法 该方法只适合公共成员方法
	 * @param obj: 对象
	 * @param fieldName: 属性名
	 * @return Object: 属性值
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @author wml
	 */
	public static Object getFieldValueByGetMethod(Object obj, String fieldName) throws SecurityException,
			NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
		Class<?> objClass = obj.getClass();
		Method method = objClass.getMethod("get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1));
		return method.invoke(obj);
	}

	/**
	 * 将Object对象的属性赋值，通过set方法
	 * @param obj: 对象
	 * @param fieldName: 属性名
	 * @param fieldValue: 属性值
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @author wml
	 */
	public static void setFieldValueBySetMethod(Object obj, String fieldName, Object fieldValue)
			throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException,
			InvocationTargetException {
		if (fieldValue != null) {
			Class<?> objClass = obj.getClass();
			Method method = objClass.getMethod(
					"set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1), fieldValue.getClass());
			method.invoke(obj, fieldValue);
		}
	}

	/**
	 * copy对象的属性值，从源对象fromObj copy 到目标对象toObj
	 * @param fromObj: 源对象
	 * @param toObj: 目标对象
	 * @param fieldName: 属性名
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @author wml
	 */
	public static void copyProperty(Object fromObj, Object toObj, String fieldName) throws SecurityException,
			NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
		Object fieldValue = getFieldValueByGetMethod(fromObj, fieldName);
		if (fieldValue != null) {
			setFieldValueBySetMethod(toObj, fieldName, fieldValue);
		}
	}

	/**
	 * copy对象的属性值，从源对象fromObj copy 到目标对象toObj，可以一次性copy多个属性
	 * @param fromObj: 源对象
	 * @param toObj: 目标对象
	 * @param fieldNameList: 属性名集合
	 * @throws SecurityException
	 * @throws IllegalArgumentException
	 * @throws NoSuchMethodException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @author wml
	 */
	public static void copyProperty(Object fromObj, Object toObj, List<String> fieldNameList) throws SecurityException,
			IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
		for (String fieldName : fieldNameList) {
			copyProperty(fromObj, toObj, fieldName);
		}
	}

	/**
	 * copy对象的属性值，从源对象fromObj copy 到目标对象toObj
	 * 自动匹配方法名称相同的，进行赋值
	 * 源对象值为null的则被忽略，不会赋值
	 * @param toObj: 目标对象
	 * @param fromObj: 源对象
	 * @throws SecurityException
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException void
	 * @author wml
	 */
	public static void copyPropertyNotNull(Object toObject, Object fromObject) throws SecurityException,
			IllegalArgumentException, IllegalAccessException, InvocationTargetException {
		Class<?> fromObjectClass = fromObject.getClass();
		Class<?> toObjectClass = toObject.getClass();
		// 返回全部方法，包含受保护的
		Field[] fields = fromObjectClass.getDeclaredFields();
		for (Field field : fields) {
			Method getMethod = null;
			try {
				getMethod = fromObjectClass.getMethod("get" + field.getName().substring(0, 1).toUpperCase()
						+ field.getName().substring(1));
			}
			catch (NoSuchMethodException e) {
				// 找不到方法则跳过本次循环
				continue;
			}
			Object value = getMethod.invoke(fromObject);
			
			// 如果值为null，不赋值，跳过
			if (value == null) {
				continue;
			}
			Method setMethod = null;
			try {
				setMethod = toObjectClass.getMethod("set" + field.getName().substring(0, 1).toUpperCase()
						+ field.getName().substring(1), field.getType());
			}
			catch (NoSuchMethodException e) {
				// 找不到方法则跳过本次循环
				continue;
			}
			setMethod.invoke(toObject, value);
		}
	}

	/**
	 * 通过给定的类名、方法名，执行指定类的方法
	 * @param className: 类名，从包名开始
	 * @param methodName: 方法名
	 * @param parameterObj
	 * @return Object: 方法返回值
	 * @throws ClassNotFoundException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 * @author wml
	 */
	public static Object runMethod(String className, String methodName, Object... parameterObj)
			throws ClassNotFoundException, InstantiationException, IllegalAccessException, SecurityException,
			NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
		Class<?> objClass = Class.forName(className);
		Object object = objClass.newInstance();
		Method method = objClass.getMethod(methodName, object2class(parameterObj));
		return method.invoke(object, parameterObj);
	}

	/**
	 * object对象数组转换成Class数组
	 * @param objs object数组
	 * @return
	 * @author wml
	 */
	private static Class<?>[] object2class(Object[] objs) {
		Class<?>[] classes = new Class<?>[objs.length];
		for (int i = 0; i < objs.length; i++) {
			classes[i] = objs[i].getClass();
		}
		return classes;
	}

	/**
	 * 拷贝对象并生成新的对象，通过属性拷贝 包含私有的属性
	 * @param obj: 待拷贝的对象
	 * @return Object: 拷贝后生产的新对象
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @author wml
	 */
	public static Object copyObject(Object obj) throws InstantiationException, IllegalAccessException {
		Class<?> objClass = obj.getClass();
		Object newObj = objClass.newInstance();
		// 返回全部方法，包含受保护的
		Field[] fields = objClass.getDeclaredFields();
		for (Field field : fields) {
			// accessible 设置为true，禁用访问控制检查
			field.setAccessible(true);
			field.set(newObj, field.get(obj));
		}
		return newObj;
	}

	/**
	 * 拷贝对象并生成新的对象，通过get、set方法拷贝 只使用公共的方法
	 * @param obj: 待拷贝的对象
	 * @return Object: 拷贝后生产的新对象
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 * @author wml
	 */
	public static Object copyBean(Object obj) throws InstantiationException, IllegalAccessException, SecurityException,
			NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
		Class<?> objClass = obj.getClass();
		Object newObj = objClass.newInstance();
		// 返回全部方法，包含受保护的
		Field[] fields = objClass.getDeclaredFields();
		for (Field field : fields) {
			Method getMethod = objClass.getMethod("get" + field.getName().substring(0, 1).toUpperCase()
					+ field.getName().substring(1));
			Object value = getMethod.invoke(obj);
			Method setMethod = objClass.getMethod("set" + field.getName().substring(0, 1).toUpperCase()
					+ field.getName().substring(1), field.getType());
			setMethod.invoke(newObj, value);
		}
		return newObj;
	}
}
